#include "translatortest.h"
#include "core/translator.h"
#include "core/sentence.h"
#include "literals/operator.h"
#include "literals/bracket.h"
#include "literals/delta.h"

TranslatorTest::TranslatorTest(QObject *parent) :
  QObject(parent),
  translator(nullptr), 
  expression(nullptr)
  {
  }

void TranslatorTest::initTestCase()
  {
  translator = new Translator();
  expression = new Expression();
  }


void TranslatorTest::testIdioticInput_data()
  {
  QTest::addColumn<QString>("input");  
  QTest::addColumn<QString>("output");
  
  QTest::newRow("1") << "a_i " << "a_i";
  QTest::newRow("2") << " a_i" << "a_i";
  QTest::newRow("3") << " a_{i }" << "a_i";
  QTest::newRow("4") << "( a_i)" << "(a_i)";
  QTest::newRow("5") << "(a_i )" << "(a_i)";
  QTest::newRow("6") << "f_{a i}" << "f(a,i)";
  QTest::newRow("7") << "f_i" << "f(i)";
  QTest::newRow("8") << "f_ijk" << "f(ijk)";
  QTest::newRow("9") << "f_{i}f_{j}" << "f(i) f(j)";
  QTest::newRow("10") << "  a_{\\bar{\\s}}" << "a_\\bar{\\s}";
  QTest::newRow("11") << "1+2" << "1 + 2";
  QTest::newRow("12") << "1+ 2" << "1 + 2";
  QTest::newRow("13") << "delta(1, 2)" << "delta(1,2)";
  QTest::newRow("14") << "delta(1 ,2)" << "delta(1,2)";
  QTest::newRow("15") << "delta(1 , 2)" << "delta(1,2)";
  }

void TranslatorTest::testIdioticInput()
  {
  QFETCH(QString, input);
  QFETCH(QString, output);
  QVERIFY(translator->stringToExp(input, *expression));
  QCOMPARE(translator->expToString(*expression), output);
  }

void TranslatorTest::testSameInSameOut_data()
  {  
  QTest::addColumn<QString>("input");
  
  QTest::newRow("1") << "delta(x,y) (a_i)";
  QTest::newRow("2") << "3.13 delta(x,y) - 2.2 b_y a_x";
  QTest::newRow("3") << "-1 - delta(x,y) + 3.4 - b_y a_x + a_x - 2";
  QTest::newRow("4") << "2 a_1 b_2 a_1 - 21 b_2 - a5 a_7";
  QTest::newRow("5") << "a b + d + a b c_i";
  QTest::newRow("6") << "x (2 a_i + b_j)";
  QTest::newRow("7") << "2 x a_{i j} + x b_{j i}";
  QTest::newRow("8") << "x() + func(arg1,arg2)";
  QTest::newRow("9") << "x(x) - c^{\\dagger}(i)";
  QTest::newRow("10") << "x(x,y)";
  QTest::newRow("11") << "delta(%1.0,%2.0) - b_%2 a_%1";
  }

void TranslatorTest::testSameInSameOut()
  {
  QFETCH(QString, input);
  QVERIFY(translator->stringToExp(input, *expression));
  QCOMPARE(translator->expToString(*expression), input);
  }

void TranslatorTest::testStringToSentence_data()
  {
  QTest::addColumn<QString>("input");

  QTest::newRow("1") << "delta(x,y) f(one,{a2e,arg3)";
  QTest::newRow("2") << "-2 b_2";
  QTest::newRow("3") << "2 a_1 b_2 a_1";
  }

void TranslatorTest::testStringToSentence()
  {
  QFETCH(QString, input);
  Sentence sen;
  expression->clear();

  bool succeeded = translator->stringToSentence(input, sen);
  expression->push_back(std::move(sen));
  QVERIFY(succeeded);
  if (succeeded)
    QCOMPARE(translator->expToString(*expression), input);

  }

void TranslatorTest::testExpToString_data()
  {
  QTest::addColumn<Expression>("input");
  QTest::addColumn<QString>("output");

    {
    Expression exp;
    Sentence s;
      {
      Word *w = new Delta("delta", "x", "y");
      s.insert(s.size(), w);
      }
      {
      QStringList qsl;
      qsl << "one" << "{a2e" << "arg3";
      Word *w = new Function("f", qsl);
      s.insert(s.size(), w);
    }
    exp.push_back(s);
    QTest::newRow("1") << exp << "delta(x,y) f(one,{a2e,arg3)";
    }

    {
    Expression exp;
    Sentence s;
    Word *wa = new Operator("a", "1");
    Word *wb = new Operator("b", "2");
    Word *wc = new Operator("a", "\\bar{\\s}");
    s.insert(s.size(), wa);
    s.insert(s.size(), wb);
    s.insert(s.size(), wc);
    s.setCoefficient(2);
    exp.push_back(s);
    QTest::newRow("2") << exp << "2 a_1 b_2 a_\\bar{\\s}";
    }

    {
    Expression exp;
    Sentence sentenceOne;
    Word *wa = new Operator("a", "1");
    Word *wb = new Operator("b", "2");

    
    Bracket *bracketExp = new Bracket();
    Sentence bracketSentenceOne;
    Word *bracketWa = new Operator("a", "1");
    bracketSentenceOne.insert(bracketSentenceOne.size(), bracketWa);
    Sentence bracketSentenceTwo;
    Word *bracketWb = new Operator("b", "2");
    bracketSentenceTwo.insert(bracketSentenceTwo.size(), bracketWb);
    bracketSentenceTwo.setCoefficient(-2);
    bracketExp->push_back(std::move(bracketSentenceOne));
    bracketExp->push_back(std::move(bracketSentenceTwo));

    Sentence sentenceTwo;
    QStringList functionArguments;
    functionArguments << "\\bar{\\s}";
    Word *wd = new Function("fu", functionArguments);
    sentenceTwo.insert(sentenceTwo.size(), wd);
    sentenceTwo.setCoefficient(-5);

    sentenceOne.insert(sentenceOne.size(), wa);
    sentenceOne.insert(sentenceOne.size(), wb);
    sentenceOne.insert(sentenceOne.size(), bracketExp);
    sentenceOne.setCoefficient(2);
    exp.push_back(sentenceOne);
    exp.push_back(sentenceTwo);
    QTest::newRow("3") << exp << "2 a_1 b_2 (a_1 - 2 b_2) - 5 fu(\\bar{\\s})";
    }

    {
    Expression exp;
    Sentence s;
    exp.push_back(s);
    QTest::newRow("4") << exp << "1";
    }
  }

void TranslatorTest::testExpToString()
  {
  QFETCH(Expression, input);
  QFETCH(QString, output);

  QCOMPARE(translator->expToString(input), output);
  }

void TranslatorTest::cleanupTestCase()
  {
  delete translator;
  delete expression;
  }
